<?php
/**
 * Created by PhpStorm.
 * User: TS
 * Date: 2017/4/4
 * Time: 17:09
 */
namespace  core;

use core\http\Response;
use core\http\Request;

class App {
	
	public static function run()
	{
		self::start();
		self::initConfig();
		Router::init();
		self::dispatch();
	}

	public static function error()
	{
		Request::getInstance()->module('index');
		Request::getInstance()->controller('error');
		Request::getInstance()->action('error');
		self::dispatch();
	}

    /**
     * 起始方法
     */
	public static function start()
    {
        defined('XT_START') or define('XT_START', microtime(true));
    }

    /**
     * 加载配置文件
     * @param string $module
     */
    public static function initConfig($module = 'index')
    {
        Config::loadModuleConfig('common');
        Config::loadModuleConfig($module);
    }

    protected static function initDbConfig()
    {
        DB::connect();
    }

    /**
     * 调度mvc
     * @return mixed
     */
    public static function dispatch()
    {
        $request = Request::getInstance();
        $reflectionClass = self::invokeClass('\\apps\\'. $request->module() .'\\controller\\' . $request->controller());
        $reflect = new \ReflectionMethod($reflectionClass, $request->action());

        $args = self::getReflectionParams($reflect);

        return $reflect->invokeArgs(isset($reflectionClass) ? $reflectionClass : null, $args);
    }

    /**
     * 反射类参数构建
     * @param \ReflectionMethod $reflect
     * @return array
     */
    private static function getReflectionParams(\ReflectionMethod $reflect)
    {
        $args = [];
        if ($reflect->getNumberOfParameters() > 0) {
            $params = $reflect->getParameters();
            foreach ($params as $param) {
                if ($class = $param->getClass()) {
                    $className = $class->getName();
                    $args[] = method_exists($className, 'getInstance') ? $className::getInstance() : new $className;
                } else $args[] = Request::getInstance()->get($param->getName(), '', 'trim,strip_tags');
            }
        }
        return $args;
    }

    /**
     * 结束方法
     */
    public static function end()
    {

    }

    /**
     * 执行函数或者闭包方法 支持参数调用
     * @access public
     * @param string|array|\Closure $function 函数或者闭包
     * @param array                 $vars     变量
     * @return mixed
     */
    public static function invokeFunction($function, $vars = [])
    {
        $reflect = new \ReflectionFunction($function);
        // 记录执行信息
        return $reflect->invokeArgs($vars);
    }

    /**
     * 调用反射执行类的方法 支持参数绑定
     * @access public
     * @param string|array $method 方法
     * @param array        $vars   变量
     * @return mixed
     */
    public static function invokeMethod($method, $vars = [])
    {
        if (is_array($method)) {
            $class   = is_object($method[0]) ? $method[0] : self::invokeClass($method[0]);
            $reflect = new \ReflectionMethod($class, $method[1]);
        } else {
            // 静态方法
            $reflect = new \ReflectionMethod($method);
        }

        return $reflect->invokeArgs(isset($class) ? $class : null, $vars);
    }

    /**
     * 调用反射执行类的实例化 支持依赖注入
     * @access public
     * @param string    $class 类名
     * @param array     $vars  变量
     * @return mixed
     */
    public static function invokeClass($class, $vars = [])
    {
        $reflect     = new \ReflectionClass($class);
        $constructor = $reflect->getConstructor();

        if ($constructor)  $vars = self::getReflectionParams($constructor);

        return $reflect->newInstanceArgs($vars);
    }
}

